package dnl.utils.jdbc.impexp;

import dnl.persistence.JdbcToCsv;
import dnl.persistence.JdbcToolz;
import dnl.persistence.TableInfo;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author Daniel Orr
 */
public class JdbcExport {

    private static final Logger logger = LoggerFactory.getLogger(JdbcExport.class);

    private DataSource dataSource;

    private List<String> tableNames;

    private MetadataRegistry metadataRegistry = new MetadataRegistry();

    private File targetDir;

    public JdbcExport(DataSource dataSource, File targetDir, List<String> tableNames) {
        this.dataSource = dataSource;
        this.tableNames = new ArrayList<>(tableNames);
        setTargetDir(targetDir);
    }

    public JdbcExport(DataSource dataSource, File targetDir, String... tableNames) {
        this.dataSource = dataSource;
        this.tableNames = new ArrayList<>(Arrays.asList(tableNames));
        setTargetDir(targetDir);

    }

    private void setTargetDir(File targetDir) {
        if (!targetDir.exists()) {
            try {
                FileUtils.forceMkdir(targetDir);
            } catch (IOException e) {
                throw new IllegalStateException(e);
            }
        }
        if (!targetDir.isDirectory()) {
            throw new IllegalArgumentException("Not a directory: " + targetDir.getAbsolutePath());
        }
        this.targetDir = targetDir;
    }

    public List<String> getTableNames() {
        return Collections.unmodifiableList(tableNames);
    }

    public void export() throws SQLException, IOException {
        logger.debug("Acquiring a connection.");
        final Connection connection = dataSource.getConnection();
        logger.debug("Start processing {} tables.", tableNames.size());
        for (String tableName : tableNames) {
            final TableInfo ti = JdbcToolz.getTableInfo(connection, tableName);
            metadataRegistry.addSourceTableInfo(ti);
            MetadataRegistry.persistToFile(metadataRegistry, new File(targetDir, "metadata.xml"));

            if (JdbcToolz.tableExists(tableName, connection)) {
                logger.debug("Verified table {}.", tableName);
                StringBuilder sb = new StringBuilder("select * from ");
                sb.append(tableName);
                JdbcToCsv jdbcToCsv = new JdbcToCsv(sb.toString(), connection);
                jdbcToCsv.setWriteColumnLabels(false);
                File csvTarget = new File(targetDir, tableName + ".csv");
                logger.info("Exporting table '{}'", tableName);
                jdbcToCsv.exportTo(csvTarget);
            } else {
                logger.error("Attempting to export non existent table '{}'", tableName);
            }
        }
    }
}
